﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.TestManagement.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace TFSTools.TFSLibrary.TestManagement
{
    public sealed class TFSTestSuite : TFSServerEntity
    {
        private ITestSuiteBase serverTestSuite;
        private TFSTestPlan tfsTestPlan;

        private TFSTestSuiteCollection subSuites = null;

        internal TFSTestSuite(TFSTestPlan testPlan, TFSTestSuite parent, ITestSuiteBase testSuite)
            : base(testPlan.Connection)
        {
            this.serverTestSuite = testSuite;
            this.tfsTestPlan = testPlan;
            this.Parent = parent;
        }

        internal ITestSuiteBase ServerEntity { get { return this.serverTestSuite; } }

        public TFSTestPlan TestPlan { get { return this.tfsTestPlan; } }

        public override string ToString() 
        {
            return this.serverTestSuite.ToString();
        }

        public int Id { get { return this.serverTestSuite.Id; } }

        public string Title { get { return this.serverTestSuite.Title; } }

        public string Description { get { return this.serverTestSuite.Description; } }

        public string Iteration { get { return this.serverTestSuite.State.ToString(); } }

        public TFSTestSuite Parent { get; private set; }

        public TFSTestSuiteCollection SubSuites
        {
            get
            {
                if (this.subSuites == null)
                {
                    if (this.serverTestSuite is IStaticTestSuite)
                    {
                        var staticSuite = (IStaticTestSuite)this.serverTestSuite;
                        this.subSuites = TFSTestSuiteCollection.Create(this.tfsTestPlan, this, staticSuite.SubSuites);
                    }
                    else
                    {
                        this.subSuites = new TFSTestSuiteCollection(this.tfsTestPlan);
                    }
                }

                return this.subSuites;
            }
        }

        public TFSTestCaseCollection GetTestCases(bool includeSubSuites)
        {
            if (includeSubSuites)
            {
                return TFSTestCaseCollection.Create(this.Connection, this.serverTestSuite.AllTestCases);
            }
            else
            {
                return TFSTestCaseCollection.Create(this.Connection, this.serverTestSuite.TestCases);
            }
        }

        public TFSWorkItemCollection GetTestCaseWorkItems(bool includeSubSuites)
        {
            if (includeSubSuites)
            {
                var workItems = from testCase
                                in this.serverTestSuite.AllTestCases
                                select new TFSWorkItem(this.Connection, testCase.WorkItem);

                return new TFSWorkItemCollection(this.Connection, workItems.ToArray());
            }
            else
            {
                var workItems = from testCase
                                in this.serverTestSuite.TestCases
                                select new TFSWorkItem(this.Connection, testCase.TestCase.WorkItem);

                return new TFSWorkItemCollection(this.Connection, workItems.ToArray());
            }
        }

        public int TestCaseCount
        {
            get { return this.serverTestSuite.AllTestCases.Count; }
        }
    }

    public sealed class TFSTestSuiteCollection : TFSServerEntityCollection<TFSTestSuite>
    {
        private TFSTestPlan tfsTestPlan;

        public TFSTestSuiteCollection(TFSTestPlan testPlan)
            : base(testPlan.Connection)
        {
            this.ValidateTestTeamProject(testPlan);
        }

        public TFSTestSuiteCollection(TFSTestPlan testPlan, IList<TFSTestSuite> list)
            : base(testPlan.Connection, list)
        {
            this.ValidateTestTeamProject(testPlan);
        }

        public TFSTestSuiteCollection(TFSTestPlan testPlan, int capacity)
            : base(testPlan.Connection, capacity)
        {
            this.ValidateTestTeamProject(testPlan);
        }

        private void ValidateTestTeamProject(TFSTestPlan testPlan)
        {
            if (testPlan == null)
            {
                throw new InvalidOperationException("TFSTestPlan must be specified for TFSTestSuiteCollection.");
            }

            this.tfsTestPlan = testPlan;
        }

        internal static TFSTestSuiteCollection Create(TFSTestPlan testPlan, TFSTestSuite parent, ITestSuiteCollection collection)
        {
            var list = new List<TFSTestSuite>(collection.Count);

            foreach (ITestSuiteBase testSuite in collection)
            {
                list.Add(new TFSTestSuite(testPlan, parent, testSuite));
            }

            return new TFSTestSuiteCollection(testPlan, list);
        }
    }
}
